package cn.edu.hbvtc.qms.service.impl;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityMessageSource;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.transaction.annotation.Transactional;

import cn.edu.hbvtc.qms.domain.Category;
import cn.edu.hbvtc.qms.domain.Clazz;
import cn.edu.hbvtc.qms.domain.ClazzArrangement;
import cn.edu.hbvtc.qms.domain.Criteria;
import cn.edu.hbvtc.qms.domain.Department;
import cn.edu.hbvtc.qms.domain.EvalPeriod;
import cn.edu.hbvtc.qms.domain.Evaluation;
import cn.edu.hbvtc.qms.domain.Item;
import cn.edu.hbvtc.qms.domain.Role;
import cn.edu.hbvtc.qms.domain.Teacher;
import cn.edu.hbvtc.qms.domain.Term;
import cn.edu.hbvtc.qms.domain.User;
import cn.edu.hbvtc.qms.persist.IClazzArrangementDao;
import cn.edu.hbvtc.qms.persist.IEvalPeriodDao;
import cn.edu.hbvtc.qms.persist.IEvaluationDao;
import cn.edu.hbvtc.qms.persist.IItemDao;
import cn.edu.hbvtc.qms.persist.IUserDao;
import cn.edu.hbvtc.qms.persist.ICategoryDao;
import cn.edu.hbvtc.qms.persist.ICriteriaDao;
import cn.edu.hbvtc.qms.service.IEvaluationService;

@Transactional
public class EvaluationService implements IEvaluationService {

	private IUserDao userDao = null;
	private ICategoryDao categoryDao = null;
	private ICriteriaDao criteriaDao = null;
	private IItemDao itemDao = null;
	private IClazzArrangementDao clazzArrangementDao = null;
	private IEvaluationDao evaluationDao = null;
	private IEvalPeriodDao evalPeriodDao = null;

	protected MessageSourceAccessor messages = SpringSecurityMessageSource
			.getAccessor();
	
	public IUserDao getUserDao() {
		return userDao;
	}

	public void setUserDao(IUserDao userDao) {
		this.userDao = userDao;
	}
	
	public ICategoryDao getCategoryDao() {
		return categoryDao;
	}

	public void setCategoryDao(ICategoryDao categoryDao) {
		this.categoryDao = categoryDao;
	}

	public ICriteriaDao getCriteriaDao() {
		return criteriaDao;
	}

	public void setCriteriaDao(ICriteriaDao criteriaDao) {
		this.criteriaDao = criteriaDao;
	}

	public IItemDao getItemDao() {
		return itemDao;
	}

	public void setItemDao(IItemDao itemDao) {
		this.itemDao = itemDao;
	}

	public IClazzArrangementDao getClazzArrangementDao() {
		return clazzArrangementDao;
	}

	public void setClazzArrangementDao(IClazzArrangementDao clazzArrangementDao) {
		this.clazzArrangementDao = clazzArrangementDao;
	}

	public IEvaluationDao getEvaluationDao() {
		return evaluationDao;
	}

	public void setEvaluationDao(IEvaluationDao evaluationDao) {
		this.evaluationDao = evaluationDao;
	}

	public IEvalPeriodDao getEvalPeriodDao() {
		return evalPeriodDao;
	}

	public void setEvalPeriodDao(IEvalPeriodDao evalPeriodDao) {
		this.evalPeriodDao = evalPeriodDao;
	}

	@Override
	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException, DataAccessException {
		User user = userDao.findUserByUserName(username);

		if (user == null) {
			throw new UsernameNotFoundException(messages.getMessage(
					"JdbcDaoImpl.notFound", new Object[] { username },
					"Username {0} not found"), username);
		}

		Set<Role> roles = user.getRoles();
		if (roles == null || roles.size() == 0) {
			throw new UsernameNotFoundException(messages.getMessage(
					"JdbcDaoImpl.notAuthority", new Object[] { username },
					"User {0} has no GrantedAuthority"), username);
		}

		Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
		for (Iterator<Role> iter = roles.iterator(); iter.hasNext();) {
			Role role = (Role) iter.next();
			GrantedAuthority authority = new GrantedAuthorityImpl("ROLE_"
					+ role.getName());
			authorities.add(authority);
		}

		return new org.springframework.security.core.userdetails.User(user
				.getUsername(), user.getPassword(), true, true, true, true,
				authorities);
	}

	@Override
	public void deleteCategoryById(int id) {
		Category category =categoryDao.findById(id);
		categoryDao.delete(category);
	}

	@Override
	public void deleteCriteriaById(int id) {
		Criteria criteria = criteriaDao.findById(id);
		criteriaDao.delete(criteria);
	}

	@Override
	public void deleteItemById(int id) {
		Item item = itemDao.findById(id);
		itemDao.delete(item);
	}

	@Override
	public Category findCategoryById(int id) {
		return categoryDao.findById(id);
	}

	@Override
	public List<Category> findCategorys() {
		return categoryDao.findAll();
	}
	
	@Override
	public List<Category> findCategorysOfCriteria(Criteria criteria) {
		return categoryDao.findCategorysOfCriteria(criteria.getId());
	}

	@Override
	public Criteria findCriteriaById(int id) {
		return criteriaDao.findById(id);
	}

	@Override
	public List<Criteria> findCriterias() {
		return criteriaDao.findAll();
	}

	@Override
	public Item findItemById(int id) {
		return itemDao.findById(id);
	}

	@Override
	public List<Item> findItems() {
		return itemDao.findAll();
	}

	@Override
	public void saveCategory(Category category) {
			categoryDao.save(category);
	}

	@Override
	public void saveCriteria(Criteria criteria) {
		criteriaDao.save(criteria);
	}

	@Override
	public void saveItem(Item item) {
		itemDao.save(item);
	}

	@Override
	public void updateCategory(Category category) {
		categoryDao.update(category);
	}

	@Override
	public void updateCriteria(Criteria criteria) {
		criteriaDao.update(criteria);
	}

	@Override
	public void updateItem(Item item) {
		itemDao.update(item);
	}

	@Override
	public List<Item> findItemsOfCategory(Category category) {
		return itemDao.findItemsOfCategory(category.getId());
	}

	@Override
	public void deleteClazzArrangementById(int id) {
		ClazzArrangement clazzArrangement = clazzArrangementDao.findById(id);
		clazzArrangementDao.delete(clazzArrangement);
	}
	
	@Override
	public ClazzArrangement findClazzArrangementById(int id) {
		return clazzArrangementDao.findById(id);
	}

	@Override
	public List<ClazzArrangement> findClazzArrangements() {
		return clazzArrangementDao.findAll();
	}

	@Override
	public void saveClazzArrangement(ClazzArrangement clazzArrangement) {
		clazzArrangementDao.save(clazzArrangement);
	}

	@Override
	public void updateClazzArrangement(ClazzArrangement clazzArrangement) {
		clazzArrangementDao.update(clazzArrangement);
	}

	@Override
	public void deleteEvaluationById(int id) {
		Evaluation eval = evaluationDao.findById(id);
		evaluationDao.delete(eval);
	}

	@Override
	public Evaluation findEvaluationById(int id) {
		return evaluationDao.findById(id);
	}

	@Override
	public List<Evaluation> findEvaluations() {
		return evaluationDao.findAll();
	}

	@Override
	public void saveEvaluation(Evaluation evaluation) {
		evaluationDao.save(evaluation);
	}

	@Override
	public void updateEvaluation(Evaluation evaluation) {
		evaluationDao.update(evaluation);
	}

	@Override
	public Criteria findCriteriaByPurposeAndEnabled(String purpose) {
		return criteriaDao.findCriteriaByPurposeAndEnabled(purpose);
	}

	@Override
	public List<Evaluation> findEvaluationByEvaluated(User evaluated) {
		return evaluationDao.findEvaluationByEvaluated(evaluated);
	}

	@Override
	public List<Evaluation> findEvaluationByEvaluated(User evaluated, Term term) {
		return evaluationDao.findEvaluationByEvaluated(evaluated, term);
	}

	@Override
	public List<ClazzArrangement> findClazzArrangementByTerm(Term term,
			Clazz clazz) {
		return clazzArrangementDao.findClazzArrangementByTerm(term, clazz);
	}

	@Override
	public List<ClazzArrangement> findClazzArrangementOfTeacher(
			Teacher teacher, Term term) {
		return clazzArrangementDao.findClazzArrangementOfTeacher(teacher, term);
	}

	@Override
	public List<Evaluation> findEvaluationByClazzArrangementAndEvalPeriod(ClazzArrangement ca, EvalPeriod ep) {
		return evaluationDao.findEvaluationByClazzArrangementAndEvalPeriod(ca, ep);
	}

	@Override
	public void deleteEvalPeriodById(int id) {
		EvalPeriod ep = evalPeriodDao.findById(id);
		evalPeriodDao.delete(ep);
	}

	@Override
	public EvalPeriod findEvalPeriodById(int id) {
		return evalPeriodDao.findById(id);
	}

	@Override
	public List<EvalPeriod> findEvalPeriods() {
		return evalPeriodDao.findAll();
	}

	@Override
	public void saveEvalPeriod(EvalPeriod evalPeriod) {
		evalPeriodDao.save(evalPeriod);
	}

	@Override
	public void updateEvalPeriod(EvalPeriod evalPeriod) {
		evalPeriodDao.update(evalPeriod);
	}

	@Override
	public EvalPeriod findEvalPeriodByUserId(int userId) {
		return evalPeriodDao.findEvalPeriodByUserId(userId);
	}

	@Override
	public EvalPeriod findEvalPeriodByDepartment(Department dept, Term term) {
		return evalPeriodDao.findEvalPeriodByDepartment(dept, term);
	}

	@Override
	public Evaluation findEvaluationByEvaluator(User evaluator,	ClazzArrangement ca, EvalPeriod ep) {
		return evaluationDao.findEvaluationByEvaluator(evaluator, ca, ep);
	}

	@Override
	public List<ClazzArrangement> findClazzArrangementOfClazz(Clazz clazz, Term term) {
		return clazzArrangementDao.findClazzArrangementOfClazz(clazz, term);
	}

	@Override
	public EvalPeriod findLateEvalPeriodByDepartmentInThisTerm(Department dept, Term term) {
		return evalPeriodDao.findLateEvalPeriodByDepartmentInThisTerm(dept, term);
	}

	@Override
	public List<EvalPeriod> findEvalPeriodsInDeptAndTerm(Department dept, Term term) {
		return evalPeriodDao.findEvalPeriodsInDeptAndTerm(dept, term);
	}

}
